package softtech.apps.callblocker;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;

import softtech.apps.utility.ApplicationConstants;
import softtech.apps.utility.FileUtility;
import softtech.apps.callblocker.model.BlackListItem;
import softtech.apps.callblocker.model.CallBlockedItem;
import softtech.apps.callblocker.model.DatabaseHanler;
import softtech.apps.callblocker.model.HeaderPhone;
import softtech.apps.callblocker.model.Setting;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.media.AudioManager;
import android.net.Uri;
import android.provider.CallLog;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds.Phone;
import android.telephony.SmsManager;
import android.telephony.TelephonyManager;
import android.util.Log;
import android.view.KeyEvent;

import com.android.internal.telephony.ITelephony;

public class ReceiverPhoneCall extends BroadcastReceiver {
	Context context = null;
	private static final String TAG = "Phone call";

	private ITelephony telephonyService;
	private ListenerPhone mListenerPhone;
	private Cursor CPhones;
	private Cursor CSim;
	/**
	 * number incoming call
	 */
	String incomingNumber;
	/**
	 * check block
	 */
	int checkbock=0;
	/**
	 * send broadcast call when have list black or unknow contact
	 */
	void updateViewWhenReceiveCall() {
		  Intent intent_call = new Intent(ApplicationConstants.TAG_BROADCAST);
		  intent_call.putExtra("receivetype", 1);
		  intent_call.putExtra("phonenumber", incomingNumber);
		  intent_call.putExtra("callmode", getSettingDefaultModeCall());
		  context.sendBroadcast(intent_call);
		 }
	@Override
	public void onReceive(Context context, Intent intent) {
		this.context = context;
		
		// check license 
		if(checkFreeTrialFinished(context)){
			return;
		}
		
		// check out going call
		if (intent.getAction().equals(Intent.ACTION_NEW_OUTGOING_CALL)) {
			String phoneNumber = intent.getExtras().getString(
					Intent.EXTRA_PHONE_NUMBER);
			Log.e(TAG, "Received Outgoing Call");
			if (phoneNumber.startsWith(ApplicationConstants.HOT_KEY)) {
				try{
					mListenerPhone = new ListenerPhone(context, intent);
					Class c = Class.forName(mListenerPhone.getMtelephony()
							.getClass().getName());
					Method m = c.getDeclaredMethod("getITelephony");
					m.setAccessible(true);
					telephonyService = (ITelephony) m.invoke(mListenerPhone
							.getMtelephony());
					telephonyService.endCall();
				}catch(Exception e){
					e.printStackTrace();
				}
				
				
				Intent intent1 = new Intent(context, ActivityDashboard.class);
				Log.i(TAG, "Starting ShaDoW Main Activity");
				intent1.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
				context.startActivity(intent1);
			}
			return;
		}
		
		
		// create widget icon
		if (TextEnable.getEnableApp(context) == 1) {
			mListenerPhone = new ListenerPhone(context, intent);
			try {
				Class c = Class.forName(mListenerPhone.getMtelephony()
						.getClass().getName());
				Method m = c.getDeclaredMethod("getITelephony");
				m.setAccessible(true);
				telephonyService = (ITelephony) m.invoke(mListenerPhone
						.getMtelephony());
				//ringer mode
				AudioManager audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
				int ringerMode=audiomanage.getRingerMode();
				// Checking Phone State (Ringing or Not)
					if (mListenerPhone.fIncomingCall() == 1) {
						
					// get Ringer mode
					
					// If the Phone is Ringing getting the Incoming number/
					
					incomingNumber = intent
							.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER);
					checkbock=0;
					// show widget incoming call
					if ((getSettingDefaultCall() & 2) == 2) {
						// open widget ico
						intent = new Intent(context, ServiceIcon.class);
						intent.putExtra("phonenumber", incomingNumber);
						if (fGetName(incomingNumber) == null) {
							intent.putExtra("name", "unknown");
						} else {
							intent.putExtra("name",
									fGetName(incomingNumber));
						}
						context.startService(intent);
					}
					
					if ((getSettingDefaultModeCall() & 240) != 0) {
						//block black list
						BlockBlacklist(incomingNumber);
						// block unknown contact
						if ((getSettingDefaultCall() & 1) == 1) {
							// call block Unknow contacts
							BlockUnknowContact(incomingNumber);
						}
						// block header number
						if ((getSettingDefaultCall() & 4) == 4) {
							// block header number
							DatabaseHanler db = new DatabaseHanler(context);
							if (db.getHeaderPhones("headerPhoneCall", null,
									null, null, null, null) != null) {
								ArrayList<HeaderPhone> ListHeader = new ArrayList<HeaderPhone>();
								ListHeader = (ArrayList<HeaderPhone>) db
										.getHeaderPhones("headerPhoneCall",
												null, null, null, null, null);
								for (int i = 0; i < ListHeader.size(); i++) {
									if (incomingNumber.contains(ListHeader.get(
											i).getHeader())) {
										blockModeCall(getSettingDefaultModeCall());

										checkbock = 1;
										return;
									}
								}
							}
						}
						//show notification
						if((getSettingDefaultCall()&8)==8){
							
						}
					}
					if(checkbock==1){
						//send broadcast incoming call
						Calendar cal = Calendar.getInstance();
						SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm");
						String datetime = df.format(cal.getTime());
						DatabaseHanler db = new DatabaseHanler(context);
						CallBlockedItem item = new CallBlockedItem(incomingNumber, datetime ,getSettingDefaultModeCall()&240);
						db.insertCallBlockItem(item);
						updateViewWhenReceiveCall();
						//delete call log in device
						deleteNumberBlockInCallLog(context, incomingNumber);
					}
				}
				// End call
				if (mListenerPhone.fIdleCall() == 1) {
					// close widget icon
					intent = new Intent(context, ServiceIcon.class);
					context.stopService(intent);
					
					//return ringer mode
					AudioManager audiomanage1 = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
					audiomanage1.setRingerMode(ringerMode);
				}
			} catch (Exception e) {
				e.printStackTrace();//
			}
		}

	}
	/**
	 * delete number is block
	 * @param mContext
	 * @param number : number block
	 */
	private void deleteNumberBlockInCallLog(Context mContext,String  number){
         
		try {
			 Thread.sleep(3000);
                Cursor cursor = mContext.getContentResolver().query(CallLog.Calls.CONTENT_URI, null, CallLog.Calls.NUMBER + " = ? ", 
                		new String[]{number}, CallLog.Calls._ID + " DESC");
                if (cursor!=null && cursor.moveToFirst()) {
                    do{
                        int idOfRowToDelete = cursor.getInt(cursor.getColumnIndex(CallLog.Calls._ID));
                        mContext.getContentResolver().delete(Uri.withAppendedPath(CallLog.Calls.CONTENT_URI, String.valueOf(idOfRowToDelete)), "", null);
                   return;
                    }while(cursor.moveToNext());
                }
            } catch (Exception ex) {
            }
	}
	/**
	 * call block black list
	 * 
	 * @param incomingNumber
	 *            : number call to phone
	 */
	private void BlockBlacklist(String incomingNumber) {
		DatabaseHanler db = new DatabaseHanler(context);
		String phone = incomingNumber;
		if(phone.contains("+") ){
			if(phone.length() > 5){
				phone = phone.substring(4);
			}
		}else{
			if(phone.length()> 5){
				phone = phone.substring(2);
			}
		}
		ArrayList<BlackListItem> ListBlack = new ArrayList<BlackListItem>();
		ListBlack = (ArrayList<BlackListItem>) db.getBlackListItem(null, null, null, null, null);
		if(ListBlack.size()!=0){
			for (BlackListItem PhoneNumber : ListBlack) {
				if (PhoneNumber.getPhoneNumber().contains(phone)) {
					blockModeCall(PhoneNumber.getMode());
					checkbock=1;
				}
			}
		}
	}

	/**
	 * call block Unknow contacts
	 * 
	 * @param incomingNumber
	 *            : number call to phone
	 */
	private void BlockUnknowContact(String incomingNumber) {
		int CheckNumber = 0;// check phone number
		// Check contact phone
		CPhones = context.getContentResolver().query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
				Phone.NUMBER + "=?", new String[] { incomingNumber }, null);// find incomingNumber in Contacts
		while (CPhones.moveToNext()) {
			String contactNumber = CPhones.getString(CPhones
					.getColumnIndex(Phone.NUMBER));
			if (incomingNumber.contentEquals(contactNumber)) {
				// have a number of Contact
				CheckNumber = 1;
			}
		}

		CPhones.close();// Close Cursor
		// Check contact SIM
		Uri simUri = Uri.parse("content://icc/adn");
		CSim = context.getContentResolver().query(simUri, null,
				Phone.NUMBER + "=?", new String[] { incomingNumber }, null);// find incomingNumber  in sim Contacts
		while (CSim.moveToNext()) {
			String SimNumber = CSim.getString(CSim.getColumnIndex("number"));
			if (incomingNumber.contentEquals(SimNumber)) {
				// have a number of Contact
				CheckNumber = 1;
			}
		}
		CSim.close();// Close Cursor
		if (CheckNumber == 0) {
			blockModeCall(getSettingDefaultModeCall());
			checkbock=1;
		}
	}
	/**
	 * Get name of phone number
	 */
	private String fGetName(String incomingNumber){
		Cursor CPhones = context.getContentResolver().query(
				ContactsContract.CommonDataKinds.Phone.CONTENT_URI, null,
				Phone.NUMBER + "=?", new String[] { incomingNumber }, null);
		// find incomingNumber in Contacts
		while (CPhones.moveToNext()) {
			String Name = CPhones.getString(CPhones.getColumnIndex(Phone.DISPLAY_NAME));
			return Name;
			}
		return null;
		}
		/**
		 * get default call
		 * @return
		 */
	private int getSettingDefaultCall(){
		DatabaseHanler db = new DatabaseHanler(context);
		Setting setting = db.getSetting(null);
		int defaultcall = setting.getBlockCallSetting();
		return defaultcall;
	}
	/**
	 * get mode call
	 * @return
	 */
	private int getSettingDefaultModeCall(){
		DatabaseHanler db = new DatabaseHanler(context);
		Setting setting = db.getSetting(null);
		int modecall = setting.getDefaultModel();
		return modecall;
	}
	/**
	 * block mode call
	 * @param status
	 */
	private void blockModeCall(int status){
		try{
		Class c = Class.forName(mListenerPhone.getMtelephony()
				.getClass().getName());
		Method m = c.getDeclaredMethod("getITelephony");
		m.setAccessible(true);
		telephonyService = (ITelephony) m.invoke(mListenerPhone
				.getMtelephony());
		}catch(Exception e){}
		/**
		 * call intent
		 */
		Intent i;
		/**
		 * send sms
		 */
		SmsManager smsmanager;
		/**
		 * set silent audio
		 */
		AudioManager audiomanage;
		
		switch (status & 240) {
		case 16:
			//
			// Answering Call
			//
			i = new Intent(Intent.ACTION_MEDIA_BUTTON);
			i.putExtra(Intent.EXTRA_KEY_EVENT,new KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEYCODE_HEADSETHOOK));
			context.sendOrderedBroadcast(i, null);
			//end call
			telephonyService.endCall();
			break;
		case 32:
			//
			// Answering Call
			//
			i = new Intent(Intent.ACTION_MEDIA_BUTTON);
			i.putExtra(Intent.EXTRA_KEY_EVENT,new KeyEvent(KeyEvent.ACTION_UP,KeyEvent.KEYCODE_HEADSETHOOK));
			context.sendOrderedBroadcast(i, null);
			//end call
			telephonyService.endCall();
			//send sms
			smsmanager = SmsManager.getDefault();
			smsmanager.sendTextMessage(incomingNumber, null, "I'm busing",
					null, null);
			break;
		case 48:
			//end call
			telephonyService.endCall();
			break;
		case 64: 
			//end call
			telephonyService.endCall();
			//send sms
			smsmanager = SmsManager.getDefault();
			smsmanager.sendTextMessage(incomingNumber, null, "I'm busing",
					null, null);
			break;
		case 80:
			audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
			audiomanage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
			break;
		case 96:
			audiomanage = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);
			audiomanage.setRingerMode(AudioManager.RINGER_MODE_SILENT);
			//hide Screen
			HideScreen(context);
			break;
		default:
			break;
		}
	}
	/**
	 * hide screen incoming call when audio silent mode
	 */
	private void HideScreen(Context context){
		
		
		Intent intentHideScreen = new Intent(Intent.ACTION_MAIN);
		intentHideScreen.addCategory(Intent.CATEGORY_LAUNCHER);
		//intentHideScreen.setClassName("softtech.apps.callblocker", "softtech.apps.callblocker.ActivityMain");
		intentHideScreen.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
				| Intent.FLAG_ACTIVITY_SINGLE_TOP);
		context.startActivity(intentHideScreen);
		((Activity) context).finish();
		
	}

	/**
	 * check if user is activated
	 * @return
	 * true: activated
	 * false: not activate
	 */
	Boolean checkIsActivated(Context context){
		FileUtility futil = new FileUtility();
		
		//
		// check license
		//
		int value1 = 0;
		int value2 = 0;
		int currentvalue = 0;
		// get old value
		try{
			value1 = Integer.parseInt(futil.getContentFileFromSdcard(ApplicationConstants.PATH_FOLDER_LICENSE, ApplicationConstants.FILE_ACTIVATE_NAME).trim());
		}catch(Exception e){
			e.printStackTrace();
		}
		
		try{
			value2 = Integer.parseInt( futil.LoadContentFile(context, ApplicationConstants.FILE_ACTIVATE_NAME).trim() );
		}catch(Exception e){
			e.printStackTrace();
		}
		
		currentvalue = value1 & value2;
		
		if(value1 ==0){
			futil.saveContentFileToSdCard(String.valueOf(currentvalue), ApplicationConstants.PATH_FOLDER_LICENSE, ApplicationConstants.FILE_ACTIVATE_NAME);
			
		}
		
		if(value2 == 0){
			futil.SaveContentFile(context, ApplicationConstants.FILE_ACTIVATE_NAME, String.valueOf(currentvalue));
		}
		
		if(currentvalue == 1){
			return true;
		}
		return false;
	}
	
	/**
	 * check free trial finished
	 * @return
	 * true: out of date
	 * false: in free time or activated
	 */
	Boolean checkFreeTrialFinished(Context context){
		FileUtility futil = new FileUtility();
		
		//
		// check license
		//
		if(checkIsActivated(context)){
			return false;
		}
			
		
		
		//
		// check free time
		//
		int value1 = 0;
		int value2 = 0;
		int currentvalue = 0;
		// get old value
		try{
			value1 = Integer.parseInt(futil.getContentFileFromSdcard(ApplicationConstants.PATH_FOLDER_LICENSE, ApplicationConstants.FILE_LICENSE_NAME).trim());
		}catch(Exception e){
			e.printStackTrace();
		}
		
		try{
			value2 = Integer.parseInt( futil.LoadContentFile(context, ApplicationConstants.FILE_LICENSE_NAME).trim() );
		}catch(Exception e){
			e.printStackTrace();
		}
		
		currentvalue = Math.max(value1, value2);
		
		if(currentvalue >= ApplicationConstants.MAX_TIME_FREE){
			return true;
		}
		return false;
	}
	
	/**
     * Issues a notification to inform the user that server has sent a message.
     */
    private static void generateNotification(Context context, String message) {
        int icon = R.drawable.ic_launcher;
        long when = System.currentTimeMillis();
        NotificationManager notificationManager = (NotificationManager)
                context.getSystemService(Context.NOTIFICATION_SERVICE);
        Notification notification = new Notification(icon, message, when);
         
        String title = context.getString(R.string.app_name);
         
        Intent notificationIntent = new Intent(context, ActivityCallHistory.class);
        // set intent so it does not start a new activity
        notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
                Intent.FLAG_ACTIVITY_SINGLE_TOP);
        PendingIntent intent =
                PendingIntent.getActivity(context, 0, notificationIntent, 0);
        notification.setLatestEventInfo(context, title, message, intent);
        notification.flags |= Notification.FLAG_AUTO_CANCEL;
         
        // Play default notification sound
        notification.defaults |= Notification.DEFAULT_SOUND;
         
        // Vibrate if vibrate is enabled
        notification.defaults |= Notification.DEFAULT_VIBRATE;
        notificationManager.notify(0, notification);     
 
    }
	
}